﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Input;
using Jade.Tools.SL.Windows.Extensions;
using JulMar.Silverlight.Interfaces;
using JulMar.Silverlight.Mvvm;
using MediaBrowserSL.RIA.MediaBrowserServiceReference;
using MediaBrowserSL.RIA.MvvmUtils;
using MediaBrowserSL.RIA.MvvmUtils.UI;
using MediaBrowserSL.RIA.Services;
using System.ServiceModel;

namespace MediaBrowserSL.RIA.ViewModels
{
    /// <summary>
    /// Authentication View Model
    /// </summary>
    public class AuthenticationViewModel : ViewModelBase
    {
        #region Private Member

        private IAuthenticationRiaServices service;
        private IErrorVisualizer errorVisualizer;
        private IAuthenticationVisualizer authenticationVisualizer;
        private ICustomMessageBoxVisualizer customMessageBoxVisualizer;
        private string login;
        private string password;
        private User newUser;
        private User userConnected;
        private bool existLoginProcess;
        private bool isLoading;
        private List<string> errors;
        private bool haveErrorWithConnection;

        #endregion

        #region Command

        public DelegatingCommand LogCommand
        {
            get;
            private set;
        }

        public ICommand GoToBackCommand
        {
            get;
            private set;
        }

        public ICommand GoToFrontCommand
        {
            get;
            private set;
        }

        public DelegatingCommand RegisterCommand
        {
            get;
            private set;
        }

        #endregion

        #region Public Properties

        public string Login
        {
            get
            {
                return login;
            }
            set
            {
                login = value;
                OnPropertyChanged("Login");
                RaiseCanExecuteChanged();
            }
        }

        public string Password
        {
            get
            {
                return password;
            }
            set
            {

                password = value;
                OnPropertyChanged("Password");
                RaiseCanExecuteChanged();
            }
        }

        public User NewUser
        {
            get
            {
                return newUser;
            }
            set
            {

                newUser = value;
                OnPropertyChanged("NewUser");
            }
        }

        public bool ExistLoginProcess
        {
            get
            {
                return existLoginProcess;
            }
            set
            {

                existLoginProcess = value;
                OnPropertyChanged("ExistLoginProcess");
            }
        }

        public bool IsLoading
        {
            get
            {
                return isLoading;
            }
            set
            {

                isLoading = value;
                OnPropertyChanged("IsLoading");
                RaiseCanExecuteChanged();
            }
        }


        #endregion

        #region Ctor

        public AuthenticationViewModel(IAuthenticationRiaServices service)
        {
            this.service = service;
            errorVisualizer = Resolve<IErrorVisualizer>();
            authenticationVisualizer = Resolve<IAuthenticationVisualizer>();
            customMessageBoxVisualizer = Resolve<ICustomMessageBoxVisualizer>();
            LogCommand = new DelegatingCommand(OnLog, CanLog);
            GoToBackCommand = new DelegatingCommand(GoToBack);
            GoToFrontCommand = new DelegatingCommand(GoToFront);
            RegisterCommand = new DelegatingCommand(OnRegister, CanRegister);
            newUser = new User();
            NewUser.PropertyChanged += NewUser_PropertyChanged;
            errors = new List<string>();
        }

        #endregion

        #region Private Methods

        private void OnLog()
        {
            IsLoading = true;
            var passCrypt = MD5Core.GetHashString(password);
            service.ExistUser(ExistUser, Login, passCrypt);
        }

        #region Login

        /// <summary>
        /// Exist User
        /// </summary>
        /// <param name="user"></param>
        /// <param name="ex"></param>
        private void ExistUser(User user, Exception ex)
        {
            IsLoading = false;
            errors.Clear();
            if (ex == null)
            {
                if (user == null)
                {
                    errors.Add("Le nom d'utilisateur ou le mot de passe que vous avez saisi est incorrect.");
                }
                else
                {
                    if (user.IsConnected)
                    {
                        StringBuilder strError = new StringBuilder();
                        strError.Append("Un utilisateur est déjà connecté avec cet identifiant ou ne s'est pas correctement déconnecté !\n");
                        strError.Append("Etes-vous sur de vouloir continuer ?");
                        haveErrorWithConnection = true;

                        if (customMessageBoxVisualizer != null)
                        {
                            userConnected = user;
                            customMessageBoxVisualizer.Show(ConfirmConnection,
                                                            strError.ToString(),
                                                            "Connection",
                                                            MessageBoxButton.OKCancel,
                                                            MessageBoxImage.Warning);
                        }
                        else
                        {
                            user.IsConnected = true;
                            service.UpdateStatut(StatutUpdated, user);
                        }
                    }
                    else
                    {
                        user.IsConnected = true;
                        service.UpdateStatut(StatutUpdated, user);
                    }
                }
            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    if (ex.GetType().Equals(typeof(FaultException<ErrorDataContract>)))
                    {
                        customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                    else
                    {
                        customMessageBoxVisualizer.Show(null, ex.Message, "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
            }

            if (authenticationVisualizer != null)
            {
                authenticationVisualizer.SetErrorsSummary(errors);
            }
        }

        /// <summary>
        /// Confirm connection
        /// </summary>
        /// <param name="r"></param>
        private void ConfirmConnection(MessageBoxResult r)
        {
            if (r == MessageBoxResult.OK)
            {
                userConnected.IsConnected = true;
                service.UpdateStatut(StatutUpdated, userConnected);
            }
        }

        /// <summary>
        /// Control Forward View
        /// </summary>
        /// <returns></returns>
        private bool CanLog()
        {
            bool result = false;

            if (!IsLoading)
            {
                result = ((!String.IsNullOrEmpty(Login)) && (!String.IsNullOrEmpty(Password)));
            }

            return result;
        }

        #endregion

        #region Register

        /// <summary>
        /// NewUser Property Changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void NewUser_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName.Equals("Login"))
            {
                var u = (User)sender;
                if (u.Login.Length == 8)
                {
                    if (!ExistLoginProcess)
                    {
                        ExistLoginProcess = true;
                        service.ExistLogin(ExistLogin, NewUser.Login);
                    }
                }
                else
                {
                    NewUser.ExistLogin = false;
                }
            }
            RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Exist Login
        /// </summary>
        /// <param name="user"></param>
        /// <param name="ex"></param>
        private void ExistLogin(bool exist, Exception ex)
        {
            ExistLoginProcess = false;
            if (ex == null)
            {
                NewUser.ExistLogin = exist;
                if (authenticationVisualizer != null)
                {
                    authenticationVisualizer.Refresh();
                }
            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        /// <summary>
        /// Add New User
        /// </summary>
        private void OnRegister()
        {
            var passCrypt = MD5Core.GetHashString(NewUser.Password);
            service.CreateUser(CreateUser, NewUser.FirstName, NewUser.LastName, NewUser.Login, passCrypt);
        }

        /// <summary>
        /// Can add new user
        /// </summary>
        private bool CanRegister()
        {
            return NewUser.ValidData();
        }

        /// <summary>
        /// Create User
        /// </summary>
        /// <param name="user"></param>
        /// <param name="ex"></param>
        private void CreateUser(int idUser, Exception ex)
        {
            if (ex == null)
            {
                NewUser.Id = idUser;

                NewUser.IsConnected = true;
                service.UpdateStatut(StatutUpdated, NewUser);
            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
        #endregion

        /// <summary>
        /// Update IsConnected Statut
        /// </summary>
        /// <param name="u"></param>
        /// <param name="ex"></param>
        private void StatutUpdated(User u, Exception ex)
        {
            if (ex == null)
            {
                CloseCommand.Execute(null);
                SessionMb.CurrentUser = u;
                SendMessage(MediatorMessages.UpdateCurrentUser, SessionMb.CurrentUser);
                Login = String.Empty;
                Password = String.Empty;

                if (customMessageBoxVisualizer != null)
                {
                    if (haveErrorWithConnection)
                    {
                        haveErrorWithConnection = false;
                        customMessageBoxVisualizer.Show(null,
                                                        "N'oubliez pas de vous déconnecter du système une fois votre navigation terminée !",
                                                        "Information",
                                                        MessageBoxButton.OK,
                                                        MessageBoxImage.Warning);
                    }
                }

            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        /// <summary>
        /// Raise can execute
        /// </summary>
        private void RaiseCanExecuteChanged()
        {
            LogCommand.RaiseCanExecuteChanged();
            RegisterCommand.RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Go to Back
        /// </summary>
        private void GoToBack()
        {
            if (authenticationVisualizer != null)
            {
                authenticationVisualizer.GoToBack();
            }
        }

        /// <summary>
        /// Go to Front
        /// </summary>
        private void GoToFront()
        {
            if (authenticationVisualizer != null)
            {
                authenticationVisualizer.GoToFront();
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// LogOut
        /// </summary>
        [MessageMediatorTarget(MediatorMessages.LogOut)]
        public void LogOut(User user)
        {
            user.IsConnected = false;
            service.UpdateStatut(null, user);
        }

        #endregion
    }
}
